""" TODO:
class BlockStreamWrapper(Stream):
    pass
class BlockStreamWriterWrapper(StreamWriter):
    pass
class BlockStreamReader(StreamReader):
    pass
"""

from __future__ import annotations
from fat.utility import BitUtility

from abc import ABC
class AbstractBlock(ABC):
    def __init__(self, data: bytearray):
        self.__size = len(data)
        self.__data = data

    def size(self) -> int:
        return self.__size

    def resize(self, size: int):
        raise NotImplementedError("resize the data & byte")

    def data(self) -> bytearray:
        return self.__data

    def __repr__(self):
        return f"AbstractBlock=>size:[{self.__size}], data:[{self.__data}]:"
    

class Block(AbstractBlock):
    @staticmethod
    def from_size(size: int = 4096) -> Block:
        size = Block.__checked_align(size)
        return Block(bytearray(size))
    @staticmethod
    def from_byte(c: int, capacity: int = 4096, repeat: int = 1) -> Block:
        if isinstance(c, int) and c >= 0 and c <= 255:
            capacity = Block.__checked_align(capacity)
            if repeat <= capacity:
                ba = bytearray(capacity)
                ba[0:repeat] = (c for i in range(repeat))
                return Block(ba)
            else:
                raise ValueError(f"repeat:{repeat} > capacity:{capacity}")
        else:
            raise ValueError(f"c:{c} is not ascii")

    """
    @staticmethod
    def from_str(s: str, codec: str ="utf-8") -> Block:
        pass
    """

    def __init__(self, data: bytearray):
        super().__init__(data)

    @staticmethod
    def __checked_align(size: int) -> int:
        return BitUtility.align_greater_equal(size, 4096)

    def __repr__(self):
        return f"Block=>size:[{self.size()}], data:[{self.data()}]:"


class Blocks(object):
    @staticmethod
    def from_list(list_blocks: list[Block]):
        if len(list_blocks) > 0:
            bs = Blocks(list_blocks[0].size())
            for b in list_blocks:
                bs.append(b)
            return bs
        else:
            return Blocks() 

    def __init__(self, block_size: int = 4096):
        self.__block_size = block_size
        self.__data = []

    def block_size(self):
        return self.__block_size

    def __len__(self):
        return len(self.__data)

    def number_of_bytes(self):  
        return len(self) * self.__block_size



    def append(self, block: Block) -> bool:
        if self.__block_size ==  block.size():
            self.__data.append(block)
            return True
        return False


    def remove(self, index: int) -> Block:
        if index >= 0 and index < len(self):
            return self.__data.pop(index)
        else:
            raise ValueError("index:[{}] out of range:[0,{})".format(index, len(self)))

    def get(self, index: int) -> Block:
        if index >= 0 and index < len(self):
            return self.__data[index]
        else:
            raise ValueError("index:[{}] out of range:[0,{})".format(index, len(self)))

    def clear(self):
        self.__data = {}

    class Iterator(object):
        def __init__(self, host):
            self.__host = host
            self.__index = 0

        def __next__(self):
            if self.__index < len(self.__host):
                v = self.__host.get(self.__index)
                self.__index = self.__index + 1
                return v
            else:
                raise StopIteration

    def __iter__(self) -> Blocks.Iterator:
        return Blocks.Iterator(self)



    """
    def push_back(self, block: Block) -> bool:
        pass
    def pop_front(self) -> Block | None:
        pass
    def push_front(self, block: Block) -> bool:
        pass
    def pop_back(self) -> Block | None:
        pass
    """


